home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_skey.idb / usr / freeware / src / skey / auth.c.z / auth.c
Encoding:
C/C++ Source or Header  |  1999-04-16  |  6.0 KB  |  294 lines

  1. /* Time-stamp: "Sat 30 Jan 1999, 13:01:51 EST by drk@sgi.com (David Kaelbling)"
  2.  * 
  3.  * A stripped-down version of skeylogin, intended for use as an IRIX
  4.  * login SITECHECK program.  A SITECHECK program must be executable,
  5.  * owned by root, and not writable by others.
  6.  *
  7.  * Usage: keyauth name [ remhost [ rusername ] ]
  8.  * Prompt for an s/key password and authenticate it.  Return status:
  9.  *     0:     Success; user was authenticated, log in.
  10.  *    1:     Failure; exit login.
  11.  *    2:     Failure; try again (don't exit login).
  12.  *    other: Use normal UNIX authentication.
  13.  */
  14.  
  15. #ifdef _BSD_SIGNALS
  16. #undef _BSD_SIGNALS
  17. #endif
  18. #ifdef _BSD_COMPAT
  19. #undef _BSD_COMPAT
  20. #endif
  21.  
  22. #include <sys/param.h>
  23. #include <sys/types.h>
  24.  
  25. #include <limits.h>
  26. #include <unistd.h>
  27. #include <stdlib.h>
  28. #include <ctype.h>
  29. #include <fcntl.h>
  30. #include <netdb.h>
  31. #include <netinet/in.h>
  32. #include <pwd.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <termio.h>
  36.  
  37. #include "skey.h"
  38.  
  39. #define SCPYN(a, b)    strncpy(a, b, sizeof(a)), a[sizeof(a)-1]='\0'
  40.  
  41. #define NMAX    32        /* Should be >= sizeof(utmpx.ut_user) */
  42.  
  43. #define SITE_OK        0
  44. #define SITE_FAIL    1
  45. #define SITE_AGAIN    2
  46. #define SITE_CONTINUE    3
  47.  
  48. /*
  49.  * This bounds the time given to login.  We initialize it here
  50.  * so it can be patched on machines where it's too small.
  51.  */
  52. int timeout = 300;
  53.  
  54. char *readskeypass(char *buf, int n);
  55. static void timedout(void);
  56. static int authfile(char *host);
  57. static int isaddr(register char *s);
  58. static long aton(register char *s);
  59. static int rdnets(long host);
  60.  
  61. void
  62. main(int argc, char *argv[])
  63. {
  64.   struct passwd *pwd;
  65.   char lusername[NMAX+1];
  66.   char host[MAXHOSTNAMELEN];
  67.   char rusername[NMAX+1];
  68.   char skeyprompt[80];
  69.   struct skey skey;
  70.   int skey_status;
  71.   char buf[LINE_MAX];
  72.  
  73.   *host = *rusername = *skeyprompt = '\0';
  74.  
  75.   /* Save the username */
  76.   if (argc > 1) {
  77.     SCPYN(lusername, argv[1]);
  78.     if (*lusername == '-') {
  79.       puts("user names may not start with '-'.");
  80.       exit(SITE_FAIL);
  81.     }
  82.     argc--;
  83.     argv++;
  84.   } else {
  85.     puts("missing user name argument.");
  86.     exit(SITE_FAIL);
  87.   }
  88.  
  89.   /* Save the remotehost */
  90.   if (argc > 1) {
  91.     SCPYN(host, argv[1]);
  92.     if (*host == '-') {
  93.       puts("remote host name may not start with '-'.");
  94.       exit(SITE_FAIL);
  95.     }
  96.     argc--;
  97.     argv++;
  98.   }
  99.  
  100.   /* Save the remote username */
  101.   if (argc > 1) {
  102.     SCPYN(rusername, argv[1]);
  103.     if (*rusername == '-') {
  104.       puts("remote user names may not start with '-'.");
  105.       exit(SITE_FAIL);
  106.     }
  107.     argc--;
  108.     argv++;
  109.   }
  110.  
  111.   /* Check for extra args. */
  112.   if (argc > 1) {
  113.     puts("too many arguments.");
  114.     exit(SITE_FAIL);
  115.   }
  116.  
  117.  
  118.   /* If this is a local login use normal password authentication. */
  119.   if (authfile(host))
  120.     exit(SITE_CONTINUE);
  121.  
  122.   /* Punt back to login if this user does not have a password. */
  123.   pwd = getpwnam(lusername);
  124.   if (pwd && *pwd->pw_passwd == '\0')
  125.     exit(SITE_CONTINUE);
  126.  
  127.  
  128.   /* Issue an s/key challenge */
  129.   if (feof(stdin)) exit(SITE_FAIL);
  130.   skey_status = skeychallenge(&skey, lusername, skeyprompt);
  131.   printf("%s\n", skeyprompt);
  132.   printf("(s/key required)\nPassword:");
  133.   fflush(stdout);
  134.  
  135.   /* Read password */
  136.   signal(SIGALRM, timedout);
  137.   alarm(timeout);
  138.   readskeypass(buf, sizeof(buf));
  139.   alarm(0);
  140.  
  141.   /* Did S/Key authentication succeed? */
  142.   if (skey_status == 0 && skeyverify(&skey, buf) == 0 && 
  143.       pwd && *pwd->pw_passwd != '*' && *pwd->pw_passwd != '#') {
  144.     if (skey.n < 5)
  145.       puts("Warning! Change password soon");
  146.     exit(SITE_OK);
  147.   }
  148.  
  149.   puts("Login incorrect");
  150.   exit(SITE_AGAIN);
  151. }
  152.  
  153. static void
  154. timedout(void)
  155. {
  156.   printf("\nLogin timed out after %d seconds\n", timeout);
  157.   exit(SITE_FAIL);
  158. }
  159.  
  160. /*
  161.  * Turn host into an IP address and then look it up in the authorization
  162.  * database to determine if ordinary password logins are OK.
  163.  */
  164. static int
  165. authfile(char *host)
  166. {
  167.   long n;
  168.   struct hostent *hp;
  169.   char **lp;
  170.  
  171.   if (*host == '\0') {
  172.     /* Local login, okay */
  173.     return 1;
  174.   }
  175.  
  176.   if (isaddr(host)) {
  177.     n = aton(host);
  178.     return rdnets(n);
  179.   } else {
  180.     hp = gethostbyname(host);
  181.     if (hp == NULL) {
  182.       printf("Unknown host %s\n", host);
  183.       return 0;
  184.     }
  185.     for (lp = hp->h_addr_list; *lp != NULL; lp++) {
  186.       memcpy((char *)&n, *lp, sizeof(n));
  187.       n = ntohl(n);
  188.       if (rdnets(n))
  189.     return 1;
  190.     }
  191.     return 0;
  192.   }
  193. }
  194.  
  195. /*
  196.  * Return non-zero if "host" is permitted to use normal password login.
  197.  */
  198. static int
  199. rdnets(long host)
  200. {
  201.   FILE *fp;
  202.   char buf[LINE_MAX], *cp;
  203.   long pattern, mask;
  204.   int permit_it;
  205.  
  206.   fp = fopen("/etc/skey.access", "r");
  207.   if (fp == NULL)
  208.     return 0;
  209.  
  210.   while(fgets(buf, sizeof(buf), fp), !feof(fp)) {
  211.     if (*buf == '#')
  212.       continue;            /* Comment */
  213.  
  214.     cp = strtok(buf, " \t");
  215.     if (cp == NULL) 
  216.       continue;
  217.  
  218.     /* two choices: permit or deny */
  219.     if (strncasecmp(cp, "permit", 4) == 0) {
  220.       permit_it = 1;
  221.     } else if (strncasecmp(cp, "deny" , 4) == 0) {
  222.       permit_it = 0;
  223.     } else {
  224.       continue; /* ignore this it is not permit/deny */
  225.     }
  226.  
  227.     cp = strtok(NULL, " \t");
  228.     if (cp == NULL)
  229.       continue;            /* Invalid line */
  230.     pattern = aton(cp);
  231.  
  232.     cp = strtok(NULL, " \t");
  233.     if (cp == NULL)
  234.       continue;            /* Invalid line */
  235.     mask = aton(cp);
  236.  
  237.     if ((host & mask) == pattern) {
  238.       fclose(fp);
  239.       return permit_it;
  240.     }
  241.   }
  242.  
  243.   fclose(fp);
  244.   return 0;
  245. }
  246.  
  247. /*
  248.  * Return non-zero if string appears to be an IP address in dotted decimal;
  249.  * return 0 otherwise (i.e., if string is a domain name)
  250.  */
  251. static int
  252. isaddr(register char *s)
  253. {
  254.   char c;
  255.  
  256.   if (s == NULL)
  257.     return 1;            /* Can't happen */
  258.  
  259.   while((c = *s++) != '\0') {
  260.     if (c != '[' && c != ']' && !isdigit(c) && c != '.')
  261.       return 0;
  262.   }
  263.   return 1;
  264. }
  265.  
  266. /*
  267.  * Convert Internet address in ascii dotted-decimal format (44.0.0.1) to
  268.  * binary IP address
  269.  */
  270. static long
  271. aton(register char *s)
  272. {
  273.   long n = 0;
  274.   register int i;
  275.  
  276.   if (s == NULL)
  277.     return 0;
  278.  
  279.   for (i = 24; i >= 0; i -= 8) {
  280.     /* Skip any leading stuff (e.g., spaces, '[') */
  281.     while(*s != '\0' && !isdigit(*s))
  282.       s++;
  283.     if (*s == '\0')
  284.       break;
  285.  
  286.     n |= atol(s) << i;
  287.     if ((s = strchr(s, '.')) == NULL)
  288.       break;
  289.     s++;
  290.   }
  291.  
  292.   return n;
  293. }
  294.